Here I want to play with it a bit more.
For example, I used the length of the path but could use the sequence of steps to modify some aesthetic.
Generate Grid
# Size of grid
n_min <- -17
n_max <- 18
# Length of segment
l <- sqrt(2) + 0.1
df <- data.frame(expand.grid(x = seq(n_min, n_max, 1), y = seq(n_min, n_max, 1)))
Create and plot the flow field:

Another possible parameter is using the valence of the coordinates to alter the angle:
# Offsets
x_o <- -0
y_o <- -0
df <- df %>%
mutate(angle = ((x - x_o) * (y - y_o)) /(n_max - n_min)^2 * 2 * pi * sign(x * y), # add the signs
xend = (x + l * cos(angle)),
yend = (y + l * sin(angle)))
df %>%
ggplot() +
geom_segment(aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(aes(x = xend,
y =yend)) +
coord_equal() +
theme_void()

The valence could be used to change the direction of the displacement of the coordinate, instead of the angle:
# Offsets
x_o <- -0
y_o <- -0
df <- df %>%
mutate(angle = ((x - x_o) * (y - y_o)) /(n_max - n_min)^2 * 2 * pi, # add the signs
xend = (x + sign(x) * l * cos(angle)),
yend = (y + sign(y) * l * sin(angle)))
df %>%
ggplot() +
geom_segment(aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(aes(x = xend,
y =yend)) +
coord_equal() +
theme_void()

Another possible parameter is an initial rotation:
# Offsets
x_o <- -0
y_o <- -0
init_r <- 1/8
df <- df %>%
mutate(angle = ((x - x_o) * (y - y_o)) /(n_max - n_min)^2 * 2 * pi + init_r * pi, # add the signs
xend = (x + l * cos(angle)),
yend = (y + l * sin(angle)))
df %>%
ggplot() +
geom_segment(aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(aes(x = xend,
y =yend)) +
coord_equal() +
theme_void()

This one has an initial rotation and valence for the angle:
# Offsets
x_o <- -0
y_o <- -0
init_r <- 1/8
df <- df %>%
mutate(angle = (((x - x_o) * (y - y_o)) /(n_max - n_min)^2 * 2 * pi + init_r * pi) * sign(x * y), # add the signs
xend = (x + l * cos(angle)),
yend = (y + l * sin(angle)))
df %>%
ggplot() +
geom_segment(aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(aes(x = xend,
y =yend)) +
coord_equal() +
theme_void()

This one has an initial rotation and valence for the displacement:
# Offsets
x_o <- -0
y_o <- -0
init_r <- 1/8
df <- df %>%
mutate(angle = ((x - x_o) * (y - y_o)) /(n_max - n_min)^2 * 2 * pi + init_r * pi, # add the signs
xend = (x + sign(x) * l * cos(angle)),
yend = (y + sign(y) * l * sin(angle)))
df %>%
ggplot() +
geom_segment(aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(aes(x = xend,
y =yend)) +
coord_equal() +
theme_void()

This one has an initial rotation, valence for the displacement and valence for the angle:
# Offsets
x_o <- -0
y_o <- -0
init_r <- 1/8
df <- df %>%
mutate(angle = (((x - x_o) * (y - y_o)) /(n_max - n_min)^2 * 2 * pi + init_r * pi) * sign(x * y), # add the signs
xend = (x + sign(x) * l * cos(angle)),
yend = (y + sign(y) * l * sin(angle)))
df %>%
ggplot() +
geom_segment(aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(aes(x = xend,
y =yend)) +
coord_equal() +
theme_void()

Make paths using the last flow field:
# Set seed for reproducibility
#set.seed(346363)
# Parameters for creating the paths
res <- 0.2 # Resolution for the path, smaller numbers create more points per path/smoother paths
n_iter <- 20 # Number of iterations per path
n_path <- 500 # Number of paths
# Sample starting points
st_point <- data.frame(x = runif(n_path, n_min, n_max),
#x = 2,
y = runif(n_path, n_min, n_max))
# Initialize data frame with paths
paths <- data.frame(x = numeric(), y = numeric(), step = numeric(), path = numeric())
for(p in 1:n_path){
paths <- rbind(paths,
data.frame(st_point[p,], step = 1, path = p))
next_x <- st_point[p, "x"]
next_y <- st_point[p, "y"]
for(i in 1:n_iter){
# With the next point, retrieve the angle of the closest point in the direction of the flow
angle <- df %>%
mutate(d = sqrt((x - next_x)^2 + (y - next_y)^2)) %>%
filter(d == min(d)) %>%
pull(angle)
# Calculate the coordinates of the new next point and bind to paths
paths <- rbind(paths,
data.frame(x = next_x + sign(next_x) * res * cos(angle), # Important to multiply by the sign of the next point
y = next_y + sign(next_y) * res * sin(angle), # Important to multiply by the sign of the next point
step = i + 1,
path = p))
# Find the next starting point for the search
next_x <- slice_tail(paths) %>%
pull(x)
next_y <- slice_tail(paths) %>%
pull(y)
# Check the boundary condition
boundary_condition <- next_x < n_min | next_x >= n_max |
next_y < n_min | next_y >= n_max
# If at the boundary set i to n_iter to complete the loop
if (boundary_condition) break
}
}
# Rename paths
paths_ex3 <- paths
Plot paths:
ggplot() +
geom_line(data = paths_ex3,
aes(x = x,
y = y,
group = path),
color = "blue",
size = 1) +
geom_segment(data = df,
aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(data = df,
aes(x = xend,
y =yend)) +
coord_equal() +
theme_void() +
theme(legend.position = "none")

Instead of lines use symbols:
ggplot() +
geom_point(data = paths_ex3 %>%
mutate(p_grid = (x * y)^2),
aes(x = x,
y = y,
group = path,
color =p_grid),
size = 1) +
coord_equal() +
theme_void() +
theme(legend.position = "none")

Add length of path to table:
paths_ex3 <- paths_ex3 %>%
left_join(paths_ex3 %>%
group_by(path) %>%
summarize(l_path = n(), # length of path
.groups = "drop"),
by = "path")
Change the size of the symbols based on their position in the path:
paths_ex3 <- paths_ex3 %>%
mutate(p_grid = (x * y)^2,
size = 1 / (abs(step - l_path/2) + 1))
ggplot(data = paths_ex3) +
geom_circle(aes(x0 = x,
y0 = y,
fill =p_grid,
color = p_grid,
r = size * res),
size = 1) +
geom_point(aes(x = x - 0.7 * size * res * pi/4,
y = y + 0.7 * size * res * pi/4),
color = "white",
size = 0.1) +
coord_equal() +
theme_void() +
theme(legend.position = "none")

Make pretty with palette Ronda:
col_palette <- mex.brewer("Ronda")
paths_ex3 <- paths_ex3 %>%
mutate(p_grid = (x * y)^2,
size = 1 / (abs(step - l_path/2) + 1))
ggplot() +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = n_min,
ymax = n_max),
fill = "black") +
geom_circle(data = paths_ex3,
aes(x0 = x,
y0 = y,
fill =p_grid,
color = p_grid,
r = 1.2 * size * res)) +
geom_point(data = paths_ex3,
aes(x = x - 1.2 * size * res * pi/4,
y = y + 1.2 * size * res * pi/4),
color = col_palette[4],
size = 0.1) +
geom_circle(aes(x0 = 0,
y0 = 0,
r = 4),
color = col_palette[4],
fill = "black",
size = 2) +
scale_color_gradientn(colors = col_palette) +
coord_equal() +
theme_void() +
theme(legend.position = "none")

Make pretty with palette Revolucion. The color depends on the position in the grid:
col_palette <- mex.brewer("Revolucion")
paths_ex3 <- paths_ex3 %>%
mutate(p_grid = (x * y)^2,
size = 1 / (abs(step - l_path/2) + 1))
ggplot() +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = n_min,
ymax = n_max),
fill = "black") +
geom_circle(data = paths_ex3,
aes(x0 = x,
y0 = y,
fill =p_grid,
color = p_grid,
r = 1.2 * size * res)) +
geom_point(data = paths_ex3,
aes(x = x - 1.2 * size * res * pi/4,
y = y + 1.2 * size * res * pi/4),
color = col_palette[4],
size = 0.1) +
geom_circle(aes(x0 = 0,
y0 = 0,
r = 4),
color = col_palette[4],
fill = "black",
size = 2) +
scale_color_gradientn(colors = col_palette) +
coord_equal() +
theme_void() +
theme(legend.position = "none")

Make pretty with palette Revolucion but now change the rate of change of the colors:
col_palette <- mex.brewer("Revolucion")
paths_ex3 <- paths_ex3 %>%
mutate(p_grid = (x * y)^2,
size = 1 / (abs(step - l_path/2) + 1))
ggplot() +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = n_min,
ymax = n_max),
fill = "black") +
geom_circle(data = paths_ex3,
aes(x0 = x,
y0 = y,
fill = p_grid^(1/3),
color = p_grid^(1/3),
r = 1.2 * size * res)) +
geom_point(data = paths_ex3,
aes(x = x - 1.2 * size * res * pi/4,
y = y + 1.2 * size * res * pi/4),
color = col_palette[4],
size = 0.1) +
geom_segment(aes(x = n_min, xend = n_max, y = 0, yend = 0),
color = col_palette[4],
size = 3) +
geom_segment(aes(x = 0, xend = 0, y = n_min, yend = n_max),
color = col_palette[4],
size = 3) +
geom_circle(aes(x0 = 0,
y0 = 0,
r = 4),
color = col_palette[4],
fill = "black",
size = 3) +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = n_min,
ymax = n_max),
fill = NA,
color = col_palette[4],
size = 3) +
scale_color_gradientn(colors = col_palette) +
coord_equal() +
theme_void() +
theme(legend.position = "none")

Make pretty with palette Revolucion but now the colors depend on the position on the path:
col_palette <- mex.brewer("Revolucion")
paths_ex3 <- paths_ex3 %>%
mutate(p_grid = (x * y)^2,
size = 1 / (abs(step - l_path/2) + 1))
ggplot() +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = n_min,
ymax = n_max),
fill = "black") +
geom_circle(data = paths_ex3,
aes(x0 = x,
y0 = y,
fill = step - l_path/2,
color = step - l_path/2,
r = 1.2 * size * res)) +
geom_point(data = paths_ex3,
aes(x = x - 1.2 * size * res * pi/4,
y = y + 1.2 * size * res * pi/4),
color = col_palette[4],
size = 0.1) +
geom_circle(aes(x0 = 0,
y0 = 0,
r = 4),
color = col_palette[4],
fill = "black",
size = 2) +
scale_color_gradientn(colors = col_palette) +
coord_equal() +
theme_void() +
theme(legend.position = "none")

Change the resolution:
# Set seed for reproducibility
#set.seed(346363)
# Parameters for creating the paths
res <- 3 # Resolution for the path, smaller numbers create more points per path/smoother paths
n_iter <- 20 # Number of iterations per path
n_path <- 5000 # Number of paths
# Sample starting points
st_point <- data.frame(x = runif(n_path, n_min, n_max),
#x = 2,
y = runif(n_path, n_min, n_max))
# Initialize data frame with paths
paths <- data.frame(x = numeric(), y = numeric(), step = numeric(), path = numeric())
for(p in 1:n_path){
paths <- rbind(paths,
data.frame(st_point[p,], step = 1, path = p))
next_x <- st_point[p, "x"]
next_y <- st_point[p, "y"]
for(i in 1:n_iter){
# With the next point, retrieve the angle of the closest point in the direction of the flow
angle <- df %>%
mutate(d = sqrt((x - next_x)^2 + (y - next_y)^2)) %>%
filter(d == min(d)) %>%
pull(angle)
# Calculate the coordinates of the new next point and bind to paths
paths <- rbind(paths,
data.frame(x = next_x + sign(next_x) * res * cos(angle), # Important to multiply by the sign of the next point
y = next_y + sign(next_y) * res * sin(angle), # Important to multiply by the sign of the next point
step = i + 1,
path = p))
# Find the next starting point for the search
next_x <- slice_tail(paths) %>%
pull(x)
next_y <- slice_tail(paths) %>%
pull(y)
# Check the boundary condition
boundary_condition <- next_x < n_min | next_x >= n_max |
next_y < n_min | next_y >= n_max
# If at the boundary set i to n_iter to complete the loop
if (boundary_condition) break
}
}
# Rename paths
paths_ex4 <- paths
Plot paths:


Experiments with angle and resolutions
# Size of grid
n_min <- -17
n_max <- 18
# Length of segment
l <- sqrt(2) + 0.1
df <- data.frame(expand.grid(x = seq(n_min, n_max, 1), y = seq(n_min, n_max, 1)))
Create new flow field:
# Offsets
x_o <- -15
y_o <- 5
init_r <- 0
d_angle <- 2
# remove the valence
df <- df %>%
mutate(angle = (((x - x_o) * (y - y_o)) /(n_max - n_min)^2 * d_angle * pi + init_r * pi),# * sign(x * y), # add the signs
xend = (x + l * cos(angle)),
yend = (y + l * sin(angle)))
df %>%
ggplot() +
geom_segment(aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(aes(x = xend,
y =yend)) +
coord_equal() +
theme_void()

Add obstacles:
df <- df %>%
mutate(r1 = sqrt((x - 8)^2 + (y - 8)^2),
r2 = sqrt((x + 8)^2 + (y + 8)^2)) %>%
filter(r1 > 4,
r2 > 4)
df %>%
ggplot() +
geom_segment(aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(aes(x = xend,
y =yend)) +
coord_equal() +
theme_void()

Change the resolution:
# Set seed for reproducibility
#set.seed(346363)
# Parameters for creating the paths
res <- 3 # Resolution for the path, smaller numbers create more points per path/smoother paths
n_iter <- 50 # Number of iterations per path
n_path <- 5000 # Number of paths
# Sample starting points
st_point <- data.frame(x = runif(n_path, n_min, n_max),
#x = 2,
y = runif(n_path, n_min, n_max)) %>%
mutate(r1 = sqrt((x - 8)^2 + (y - 8)^2),
r2 = sqrt((x + 8)^2 + (y + 8)^2)) %>%
filter(r1 > 4,
r2 > 4) %>%
select(-starts_with("r"))
# Update number of paths to account for the starting poins eliminated due to obstacles
n_path <- nrow(st_point)
# Initialize data frame with paths
paths <- data.frame(x = numeric(), y = numeric(), step = numeric(), path = numeric())
for(p in 1:n_path){
paths <- rbind(paths,
data.frame(st_point[p,], step = 1, path = p))
next_x <- st_point[p, "x"]
next_y <- st_point[p, "y"]
for(i in 1:n_iter){
# With the next point, retrieve the angle of the closest point in the direction of the flow
angle <- df %>%
mutate(d = sqrt((x - next_x)^2 + (y - next_y)^2)) %>%
filter(d == min(d))
min_d <- angle %>% pull(d)
angle <- angle %>% pull(angle)
# Calculate the coordinates of the new next point and bind to paths
paths <- rbind(paths,
data.frame(x = next_x + res * cos(angle), # Removed the valence
y = next_y + res * sin(angle), # Removed the valence
step = i + 1,
path = p))
# Find the next starting point for the search
next_x <- slice_tail(paths) %>%
pull(x)
next_y <- slice_tail(paths) %>%
pull(y)
# Check the boundary condition
boundary_condition <- next_x < n_min | next_x >= n_max |
next_y < n_min | next_y >= n_max | min_d > sqrt(2) + 0.1
# If at the boundary set i to n_iter to complete the loop
if (boundary_condition) break
}
}
# Rename paths
paths_ex5 <- paths
Plot paths:
# Add length of path to table:
paths_ex5 <- paths_ex5 %>%
left_join(paths_ex5 %>%
group_by(path) %>%
summarize(l_path = n(), # length of path
.groups = "drop"),
by = "path")
ggplot() +
geom_path(data = paths_ex5,
aes(x = x,
y = y,
group = path),
color = "blue",
size = 1) +
geom_segment(data = df,
aes(x = x,
y = y,
xend = xend,
yend = yend)) +
geom_point(data = df,
aes(x = xend,
y =yend)) +
coord_equal() +
theme_void() +
theme(legend.position = "none")

Obstacle avoidance not working great, wonder why.
Prettify:
col_palette <- mex.brewer("Revolucion")
paths_ex5 <- paths_ex5 %>%
mutate(p_grid = ((x - n_min) * (y - n_min ))^2,
size = 1 / (abs(step - l_path/2) + 1))
plot1 <- ggplot() +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = n_min,
ymax = n_max),
fill = "black") +
geom_path(data = paths_ex5 %>%
filter(x > n_min & x < n_max,
y > n_min & y < n_max),
aes(x = x,
y = y,
group = path,
color = p_grid^(1/3))) +
geom_circle(aes(x0 = -8,
y0 = -8,
r = 4),
color = col_palette[4],
fill = col_palette[8],
size = 3) +
geom_circle(aes(x0 = 8,
y0 = 8,
r = 4),
color = col_palette[4],
fill = col_palette[1],
size = 3) +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = n_min,
ymax = n_max),
fill = NA,
color = col_palette[8],
size = 3) +
scale_color_gradientn(colors = col_palette) +
coord_equal() +
theme_void() +
theme(legend.position = "none")
plot1

col_palette <- mex.brewer("Atentado")
paths_ex5 <- paths_ex5 %>%
mutate(p_grid = ((x - n_min) * (y - n_min ))^2,
size = 1 / (abs(step - l_path/2) + 1))
plot2 <- ggplot() +
geom_rect(aes(xmin = -n_min,
xmax = -n_max,
ymin = n_min,
ymax = n_max),
fill = "black") +
geom_path(data = paths_ex5 %>%
filter(x > n_min & x < n_max,
y > n_min & y < n_max),
aes(x = -x,
y = y,
group = path,
color = p_grid^(1/3))) +
geom_circle(aes(x0 = 8,
y0 = -8,
r = 4),
color = col_palette[4],
fill = col_palette[8],
size = 3) +
geom_circle(aes(x0 = -8,
y0 = 8,
r = 4),
color = col_palette[4],
fill = col_palette[1],
size = 3) +
geom_rect(aes(xmin = -n_min,
xmax = -n_max,
ymin = n_min,
ymax = n_max),
fill = NA,
color = col_palette[8],
size = 3) +
scale_color_gradientn(colors = col_palette) +
coord_equal() +
theme_void() +
theme(legend.position = "none")
plot2

col_palette <- mex.brewer("Alacena")
paths_ex5 <- paths_ex5 %>%
mutate(p_grid = ((x - n_min) * (y - n_min ))^2,
size = 1 / (abs(step - l_path/2) + 1))
plot3 <- ggplot() +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = -n_min,
ymax = -n_max),
fill = "black") +
geom_path(data = paths_ex5 %>%
filter(x > n_min & x < n_max,
y > n_min & y < n_max),
aes(x = x,
y = -y,
group = path,
color = p_grid^(1/3))) +
geom_circle(aes(x0 = 8,
y0 = -8,
r = 4),
color = col_palette[4],
fill = col_palette[8],
size = 3) +
geom_circle(aes(x0 = -8,
y0 = 8,
r = 4),
color = col_palette[4],
fill = col_palette[1],
size = 3) +
geom_rect(aes(xmin = n_min,
xmax = n_max,
ymin = -n_min,
ymax = -n_max),
fill = NA,
color = col_palette[8],
size = 3) +
scale_color_gradientn(colors = col_palette) +
coord_equal() +
theme_void() +
theme(legend.position = "none")
plot3

col_palette <- mex.brewer("Ronda")
paths_ex5 <- paths_ex5 %>%
mutate(p_grid = ((x - n_min) * (y - n_min ))^2,
size = 1 / (abs(step - l_path/2) + 1))
plot4 <- ggplot() +
geom_rect(aes(xmin = -n_min,
xmax = -n_max,
ymin = -n_min,
ymax = -n_max),
fill = "black") +
geom_path(data = paths_ex5 %>%
filter(x > n_min & x < n_max,
y > n_min & y < n_max),
aes(x = -x,
y = -y,
group = path,
color = p_grid^(1/3))) +
geom_circle(aes(x0 = -8,
y0 = -8,
r = 4),
color = col_palette[4],
fill = col_palette[8],
size = 3) +
geom_circle(aes(x0 = 8,
y0 = 8,
r = 4),
color = col_palette[4],
fill = col_palette[1],
size = 3) +
geom_rect(aes(xmin = -n_min,
xmax = -n_max,
ymin = -n_min,
ymax = -n_max),
fill = NA,
color = col_palette[8],
size = 3) +
scale_color_gradientn(colors = col_palette) +
coord_equal() +
theme_void() +
theme(legend.position = "none")
plot4


LS0tCnRpdGxlOiAiRXhwZXJpbWVudHMgd2l0aCBGaWRlbnphIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpNeSBiYXNpYyBjb2RlIGltcGxlbWVudGluZyB0aGUgRmlkZW56YSBhbGdvcml0aG0gaXMgaW4gdGhlIFJFQURNRS5SbWQgZmlsZSBpbiBgMDQtZmlkZW56YWAuCgpIZXJlIEkgd2FudCB0byBwbGF5IHdpdGggaXQgYSBiaXQgbW9yZS4KCkZvciBleGFtcGxlLCBJIHVzZWQgdGhlIGxlbmd0aCBvZiB0aGUgcGF0aCBidXQgY291bGQgdXNlIHRoZSBzZXF1ZW5jZSBvZiBzdGVwcyB0byBtb2RpZnkgc29tZSBhZXN0aGV0aWMuCgpJIHdpbGwgdXNlIHRoZSBmb2xsb3dpbmcgcGFja2FnZXM6CmBgYHtyIGxvYWQtcGFja2FnZXMsIGNhY2hlID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoZ2dmb3JjZSkKbGlicmFyeShNZXhCcmV3ZXIpCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKClRoaXMgYXJlIHRoZSBiYXNpYyBzdGVwczoKCjEuIEdlbmVyYXRlIGEgZ3JpZAotIEltcG9ydGFudCBwYXJhbWV0ZXJzOiBzaXplIG9mIHRoZSBncmlkIGFuZCB2YWxlbmNlIG9mIHRoZSBjb29yZGluYXRlcyAocG9zaXRpdmUvbmVnYXRpdmUpCgoyLiBHZW5lcmF0ZSBhIGZsb3cgZmllbGQgb24gdGhlIGdyaWQKLSBJbXBvcnRhbnQgcGFyYW1ldGVyczogb2Zmc2V0IGFuZCBmb3JtdWxhcyBmb3IgdGhlIGFuZ2xlcyBvZiB0aGUgZmxvdyBmaWVsZAoKMy4gR2VuZXJhdGUgcGF0aHMKLSBJbXBvcnRhbnQgcGFyYW1ldGVyczogcmVzb2x1dGlvbiwgbnVtYmVyIG9mIGl0ZXJhdGlvbnMgKGxlbmd0aCBvZiBwYXRoKSwgbnVtYmVyIG9mIHBhdGhzIAoKIyMgR2VuZXJhdGUgR3JpZAoKYGBge3J9CiMgU2l6ZSBvZiBncmlkCm5fbWluIDwtIC0xNyAKbl9tYXggPC0gMTgKIyBMZW5ndGggb2Ygc2VnbWVudApsIDwtIHNxcnQoMikgKyAwLjEKCmRmIDwtIGRhdGEuZnJhbWUoZXhwYW5kLmdyaWQoeCA9IHNlcShuX21pbiwgbl9tYXgsIDEpLCB5ID0gc2VxKG5fbWluLCBuX21heCwgMSkpKQpgYGAKCkNyZWF0ZSBhbmQgcGxvdCB0aGUgZmxvdyBmaWVsZDoKYGBge3J9CiMgT2Zmc2V0cwp4X28gPC0gLTAKeV9vIDwtIC0wCgpkZiA8LSBkZiAlPiUKICBtdXRhdGUoYW5nbGUgPSAoKHggLSB4X28pICogKHkgLSB5X28pKSAvKG5fbWF4IC0gbl9taW4pXjIgKiAyICogcGksCiAgICAgICAgIHhlbmQgPSAoeCArIGwgKiBjb3MoYW5nbGUpKSwKICAgICAgICAgeWVuZCA9ICh5ICsgbCAqIHNpbihhbmdsZSkpKQoKZGYgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IHgsCiAgICAgICAgICAgICAgICAgICB5ID0geSwKICAgICAgICAgICAgICAgICAgIHhlbmQgPSB4ZW5kLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IHllbmQpKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IHhlbmQsIAogICAgICAgICAgICAgICAgIHkgPXllbmQpKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpCmBgYAoKQW5vdGhlciBwb3NzaWJsZSBwYXJhbWV0ZXIgaXMgdXNpbmcgdGhlIHZhbGVuY2Ugb2YgdGhlIGNvb3JkaW5hdGVzIHRvIGFsdGVyIHRoZSBhbmdsZToKYGBge3J9CiMgT2Zmc2V0cwp4X28gPC0gLTAKeV9vIDwtIC0wCgpkZiA8LSBkZiAlPiUKICBtdXRhdGUoYW5nbGUgPSAoKHggLSB4X28pICogKHkgLSB5X28pKSAvKG5fbWF4IC0gbl9taW4pXjIgKiAyICogcGkgKiBzaWduKHggKiB5KSwgIyBhZGQgdGhlIHNpZ25zCiAgICAgICAgIHhlbmQgPSAoeCArIGwgKiBjb3MoYW5nbGUpKSwKICAgICAgICAgeWVuZCA9ICh5ICsgbCAqIHNpbihhbmdsZSkpKQoKZGYgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IHgsCiAgICAgICAgICAgICAgICAgICB5ID0geSwKICAgICAgICAgICAgICAgICAgIHhlbmQgPSB4ZW5kLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IHllbmQpKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IHhlbmQsIAogICAgICAgICAgICAgICAgIHkgPXllbmQpKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpCmBgYAoKVGhlIHZhbGVuY2UgY291bGQgYmUgdXNlZCB0byBjaGFuZ2UgdGhlIGRpcmVjdGlvbiBvZiB0aGUgZGlzcGxhY2VtZW50IG9mIHRoZSBjb29yZGluYXRlLCBpbnN0ZWFkIG9mIHRoZSBhbmdsZToKYGBge3J9CiMgT2Zmc2V0cwp4X28gPC0gLTAKeV9vIDwtIC0wCgpkZiA8LSBkZiAlPiUKICBtdXRhdGUoYW5nbGUgPSAoKHggLSB4X28pICogKHkgLSB5X28pKSAvKG5fbWF4IC0gbl9taW4pXjIgKiAyICogcGksICMgYWRkIHRoZSBzaWducwogICAgICAgICB4ZW5kID0gKHggKyBzaWduKHgpICogbCAqIGNvcyhhbmdsZSkpLAogICAgICAgICB5ZW5kID0gKHkgKyBzaWduKHkpICogbCAqIHNpbihhbmdsZSkpKQoKZGYgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IHgsCiAgICAgICAgICAgICAgICAgICB5ID0geSwKICAgICAgICAgICAgICAgICAgIHhlbmQgPSB4ZW5kLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IHllbmQpKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IHhlbmQsIAogICAgICAgICAgICAgICAgIHkgPXllbmQpKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpCmBgYAoKQW5vdGhlciBwb3NzaWJsZSBwYXJhbWV0ZXIgaXMgYW4gaW5pdGlhbCByb3RhdGlvbjoKYGBge3J9CiMgT2Zmc2V0cwp4X28gPC0gLTAKeV9vIDwtIC0wCmluaXRfciA8LSAxLzgKCmRmIDwtIGRmICU+JQogIG11dGF0ZShhbmdsZSA9ICgoeCAtIHhfbykgKiAoeSAtIHlfbykpIC8obl9tYXggLSBuX21pbileMiAqIDIgKiBwaSArIGluaXRfciAqIHBpLCAjIGFkZCB0aGUgc2lnbnMKICAgICAgICAgeGVuZCA9ICh4ICsgbCAqIGNvcyhhbmdsZSkpLAogICAgICAgICB5ZW5kID0gKHkgKyBsICogc2luKGFuZ2xlKSkpCgpkZiAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgeGVuZCA9IHhlbmQsCiAgICAgICAgICAgICAgICAgICB5ZW5kID0geWVuZCkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0geGVuZCwgCiAgICAgICAgICAgICAgICAgeSA9eWVuZCkpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkKYGBgCgpUaGlzIG9uZSBoYXMgYW4gaW5pdGlhbCByb3RhdGlvbiBhbmQgdmFsZW5jZSBmb3IgdGhlIGFuZ2xlOgpgYGB7cn0KIyBPZmZzZXRzCnhfbyA8LSAtMAp5X28gPC0gLTAKaW5pdF9yIDwtIDEvOAoKZGYgPC0gZGYgJT4lCiAgbXV0YXRlKGFuZ2xlID0gKCgoeCAtIHhfbykgKiAoeSAtIHlfbykpIC8obl9tYXggLSBuX21pbileMiAqIDIgKiBwaSArIGluaXRfciAqIHBpKSAqIHNpZ24oeCAqIHkpLCAjIGFkZCB0aGUgc2lnbnMKICAgICAgICAgeGVuZCA9ICh4ICsgbCAqIGNvcyhhbmdsZSkpLAogICAgICAgICB5ZW5kID0gKHkgKyBsICogc2luKGFuZ2xlKSkpCgpkZiAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgeGVuZCA9IHhlbmQsCiAgICAgICAgICAgICAgICAgICB5ZW5kID0geWVuZCkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0geGVuZCwgCiAgICAgICAgICAgICAgICAgeSA9eWVuZCkpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkKYGBgCgpUaGlzIG9uZSBoYXMgYW4gaW5pdGlhbCByb3RhdGlvbiBhbmQgdmFsZW5jZSBmb3IgdGhlIGRpc3BsYWNlbWVudDoKYGBge3J9CiMgT2Zmc2V0cwp4X28gPC0gLTAKeV9vIDwtIC0wCmluaXRfciA8LSAxLzgKCmRmIDwtIGRmICU+JQogIG11dGF0ZShhbmdsZSA9ICgoeCAtIHhfbykgKiAoeSAtIHlfbykpIC8obl9tYXggLSBuX21pbileMiAqIDIgKiBwaSArIGluaXRfciAqIHBpLCAjIGFkZCB0aGUgc2lnbnMKICAgICAgICAgeGVuZCA9ICh4ICsgc2lnbih4KSAqIGwgKiBjb3MoYW5nbGUpKSwKICAgICAgICAgeWVuZCA9ICh5ICsgc2lnbih5KSAqIGwgKiBzaW4oYW5nbGUpKSkKCmRmICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSB4LAogICAgICAgICAgICAgICAgICAgeSA9IHksCiAgICAgICAgICAgICAgICAgICB4ZW5kID0geGVuZCwKICAgICAgICAgICAgICAgICAgIHllbmQgPSB5ZW5kKSkgKwogIGdlb21fcG9pbnQoYWVzKHggPSB4ZW5kLCAKICAgICAgICAgICAgICAgICB5ID15ZW5kKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lX3ZvaWQoKQpgYGAKClRoaXMgb25lIGhhcyBhbiBpbml0aWFsIHJvdGF0aW9uLCB2YWxlbmNlIGZvciB0aGUgZGlzcGxhY2VtZW50IF9hbmRfIHZhbGVuY2UgZm9yIHRoZSBhbmdsZToKYGBge3J9CiMgT2Zmc2V0cwp4X28gPC0gLTAKeV9vIDwtIC0wCmluaXRfciA8LSAxLzgKCmRmIDwtIGRmICU+JQogIG11dGF0ZShhbmdsZSA9ICgoKHggLSB4X28pICogKHkgLSB5X28pKSAvKG5fbWF4IC0gbl9taW4pXjIgKiAyICogcGkgKyBpbml0X3IgKiBwaSkgKiBzaWduKHggKiB5KSwgIyBhZGQgdGhlIHNpZ25zCiAgICAgICAgIHhlbmQgPSAoeCArIHNpZ24oeCkgKiBsICogY29zKGFuZ2xlKSksCiAgICAgICAgIHllbmQgPSAoeSArIHNpZ24oeSkgKiBsICogc2luKGFuZ2xlKSkpCgpkZiAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgeGVuZCA9IHhlbmQsCiAgICAgICAgICAgICAgICAgICB5ZW5kID0geWVuZCkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0geGVuZCwgCiAgICAgICAgICAgICAgICAgeSA9eWVuZCkpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkKYGBgCgpNYWtlIHBhdGhzIHVzaW5nIHRoZSBsYXN0IGZsb3cgZmllbGQ6CmBgYHtyfQojIFNldCBzZWVkIGZvciByZXByb2R1Y2liaWxpdHkKI3NldC5zZWVkKDM0NjM2MykKCiMgUGFyYW1ldGVycyBmb3IgY3JlYXRpbmcgdGhlIHBhdGhzCnJlcyA8LSAwLjIgIyBSZXNvbHV0aW9uIGZvciB0aGUgcGF0aCwgc21hbGxlciBudW1iZXJzIGNyZWF0ZSBtb3JlIHBvaW50cyBwZXIgcGF0aC9zbW9vdGhlciBwYXRocwpuX2l0ZXIgPC0gMjAgIyBOdW1iZXIgb2YgaXRlcmF0aW9ucyBwZXIgcGF0aApuX3BhdGggPC0gNTAwICMgTnVtYmVyIG9mIHBhdGhzCgojIFNhbXBsZSBzdGFydGluZyBwb2ludHMKc3RfcG9pbnQgPC0gZGF0YS5mcmFtZSh4ID0gcnVuaWYobl9wYXRoLCBuX21pbiwgbl9tYXgpLAogICAgICAgICAgICAgICAgICAgICAgICN4ID0gMiwKICAgICAgICAgICAgICAgICAgICAgICB5ID0gcnVuaWYobl9wYXRoLCBuX21pbiwgbl9tYXgpKQoKIyBJbml0aWFsaXplIGRhdGEgZnJhbWUgd2l0aCBwYXRocwpwYXRocyA8LSBkYXRhLmZyYW1lKHggPSBudW1lcmljKCksIHkgPSBudW1lcmljKCksIHN0ZXAgPSBudW1lcmljKCksIHBhdGggPSBudW1lcmljKCkpCgpmb3IocCBpbiAxOm5fcGF0aCl7CiAgcGF0aHMgPC0gcmJpbmQocGF0aHMsCiAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZShzdF9wb2ludFtwLF0sIHN0ZXAgPSAxLCBwYXRoID0gcCkpCiAgbmV4dF94IDwtIHN0X3BvaW50W3AsICJ4Il0KICBuZXh0X3kgPC0gc3RfcG9pbnRbcCwgInkiXQogIGZvcihpIGluIDE6bl9pdGVyKXsKICAgICMgV2l0aCB0aGUgbmV4dCBwb2ludCwgcmV0cmlldmUgdGhlIGFuZ2xlIG9mIHRoZSBjbG9zZXN0IHBvaW50IGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIGZsb3cKICAgIGFuZ2xlIDwtIGRmICU+JSAKICAgICAgbXV0YXRlKGQgPSBzcXJ0KCh4IC0gbmV4dF94KV4yICsgKHkgLSBuZXh0X3kpXjIpKSAlPiUKICAgICAgZmlsdGVyKGQgPT0gbWluKGQpKSAlPiUKICAgICAgcHVsbChhbmdsZSkKICAgICMgQ2FsY3VsYXRlIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbmV3IG5leHQgcG9pbnQgYW5kIGJpbmQgdG8gcGF0aHMKICAgIHBhdGhzIDwtIHJiaW5kKHBhdGhzLAogICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSh4ID0gbmV4dF94ICsgc2lnbihuZXh0X3gpICogcmVzICogY29zKGFuZ2xlKSwgIyBJbXBvcnRhbnQgdG8gbXVsdGlwbHkgYnkgdGhlIHNpZ24gb2YgdGhlIG5leHQgcG9pbnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IG5leHRfeSArIHNpZ24obmV4dF95KSAqIHJlcyAqIHNpbihhbmdsZSksICMgSW1wb3J0YW50IHRvIG11bHRpcGx5IGJ5IHRoZSBzaWduIG9mIHRoZSBuZXh0IHBvaW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXAgPSBpICsgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IHApKQogICAgIyBGaW5kIHRoZSBuZXh0IHN0YXJ0aW5nIHBvaW50IGZvciB0aGUgc2VhcmNoCiAgICBuZXh0X3ggPC0gc2xpY2VfdGFpbChwYXRocykgJT4lCiAgICAgIHB1bGwoeCkKICAgIG5leHRfeSA8LSBzbGljZV90YWlsKHBhdGhzKSAlPiUKICAgICAgcHVsbCh5KQogICAgCiAgICAjIENoZWNrIHRoZSBib3VuZGFyeSBjb25kaXRpb24KICAgIGJvdW5kYXJ5X2NvbmRpdGlvbiA8LSBuZXh0X3ggPCBuX21pbiB8IG5leHRfeCA+PSBuX21heCB8CiAgICAgIG5leHRfeSA8IG5fbWluIHwgbmV4dF95ID49IG5fbWF4CiAgICAjIElmIGF0IHRoZSBib3VuZGFyeSBzZXQgaSB0byBuX2l0ZXIgdG8gY29tcGxldGUgdGhlIGxvb3AKICAgIGlmIChib3VuZGFyeV9jb25kaXRpb24pIGJyZWFrCiAgfQp9CgojIFJlbmFtZSBwYXRocwoKcGF0aHNfZXgzIDwtIHBhdGhzCmBgYAoKUGxvdCBwYXRoczoKYGBge3IgcGF0aHMtZXgzfQpnZ3Bsb3QoKSArIAogIGdlb21fbGluZShkYXRhID0gcGF0aHNfZXgzLAogICAgICAgICAgICBhZXMoeCA9IHgsCiAgICAgICAgICAgICAgICB5ID0geSwKICAgICAgICAgICAgICAgIGdyb3VwID0gcGF0aCksCiAgICAgICAgICAgIGNvbG9yID0gImJsdWUiLAogICAgICAgICAgICBzaXplID0gMSkgKwogIGdlb21fc2VnbWVudChkYXRhID0gZGYsCiAgICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgeGVuZCA9IHhlbmQsCiAgICAgICAgICAgICAgICAgICB5ZW5kID0geWVuZCkpICsKICBnZW9tX3BvaW50KGRhdGEgPSBkZiwKICAgICAgICAgICAgIGFlcyh4ID0geGVuZCwgCiAgICAgICAgICAgICAgICAgeSA9eWVuZCkpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKSW5zdGVhZCBvZiBsaW5lcyB1c2Ugc3ltYm9sczoKYGBge3J9CmdncGxvdCgpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gcGF0aHNfZXgzICU+JQogICAgICAgICAgICAgICBtdXRhdGUocF9ncmlkID0gKHggKiB5KV4yKSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0geSwKICAgICAgICAgICAgICAgICBncm91cCA9IHBhdGgsIAogICAgICAgICAgICAgICAgIGNvbG9yID1wX2dyaWQpLAogICAgICAgICAgICAgc2l6ZSA9IDEpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKQWRkIGxlbmd0aCBvZiBwYXRoIHRvIHRhYmxlOgpgYGB7cn0KcGF0aHNfZXgzIDwtIHBhdGhzX2V4MyAlPiUgCiAgbGVmdF9qb2luKHBhdGhzX2V4MyAlPiUKICAgICAgICAgICAgICBncm91cF9ieShwYXRoKSAlPiUKICAgICAgICAgICAgICBzdW1tYXJpemUobF9wYXRoID0gbigpLCAjIGxlbmd0aCBvZiBwYXRoCiAgICAgICAgICAgICAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpLAogICAgICAgICAgICBieSA9ICJwYXRoIikgCmBgYAoKQ2hhbmdlIHRoZSBzaXplIG9mIHRoZSBzeW1ib2xzIGJhc2VkIG9uIHRoZWlyIHBvc2l0aW9uIGluIHRoZSBwYXRoOgpgYGB7cn0KcGF0aHNfZXgzIDwtIHBhdGhzX2V4MyAlPiUKICBtdXRhdGUocF9ncmlkID0gKHggKiB5KV4yLAogICAgICAgICBzaXplID0gMSAvIChhYnMoc3RlcCAtIGxfcGF0aC8yKSArIDEpKQoKZ2dwbG90KGRhdGEgPSBwYXRoc19leDMpICsgCiAgZ2VvbV9jaXJjbGUoYWVzKHgwID0geCwKICAgICAgICAgICAgICAgICAgeTAgPSB5LCAKICAgICAgICAgICAgICAgICAgZmlsbCA9cF9ncmlkLAogICAgICAgICAgICAgICAgICBjb2xvciA9IHBfZ3JpZCwKICAgICAgICAgICAgICAgICAgciA9IHNpemUgKiByZXMpLAogICAgICAgICAgICAgIHNpemUgPSAxKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IHggLSAwLjcgKiBzaXplICogcmVzICogcGkvNCwKICAgICAgICAgICAgICAgICB5ID0geSArIDAuNyAqIHNpemUgKiByZXMgKiBwaS80KSwKICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwgCiAgICAgICAgICAgICBzaXplID0gMC4xKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCk1ha2UgcHJldHR5IHdpdGggcGFsZXR0ZSBgUm9uZGFgOgpgYGB7cn0KY29sX3BhbGV0dGUgPC0gbWV4LmJyZXdlcigiUm9uZGEiKQoKcGF0aHNfZXgzIDwtIHBhdGhzX2V4MyAlPiUKICBtdXRhdGUocF9ncmlkID0gKHggKiB5KV4yLAogICAgICAgICBzaXplID0gMSAvIChhYnMoc3RlcCAtIGxfcGF0aC8yKSArIDEpKQoKZ2dwbG90KCkgKyAKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB4bWF4ID0gbl9tYXgsIAogICAgICAgICAgICAgICAgeW1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSBuX21heCksCiAgICAgICAgICAgIGZpbGwgPSAiYmxhY2siKSArCiAgZ2VvbV9jaXJjbGUoZGF0YSA9IHBhdGhzX2V4MywKICAgICAgICAgICAgICBhZXMoeDAgPSB4LAogICAgICAgICAgICAgICAgICB5MCA9IHksCiAgICAgICAgICAgICAgICAgIGZpbGwgPXBfZ3JpZCwKICAgICAgICAgICAgICAgICAgY29sb3IgPSBwX2dyaWQsCiAgICAgICAgICAgICAgICAgIHIgPSAxLjIgKiBzaXplICogcmVzKSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHBhdGhzX2V4MywKICAgICAgICAgICAgIGFlcyh4ID0geCAtIDEuMiAqIHNpemUgKiByZXMgKiBwaS80LAogICAgICAgICAgICAgICAgIHkgPSB5ICsgMS4yICogc2l6ZSAqIHJlcyAqIHBpLzQpLAogICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVs0XSwKICAgICAgICAgICAgIHNpemUgPSAwLjEpICsKICBnZW9tX2NpcmNsZShhZXMoeDAgPSAwLAogICAgICAgICAgICAgICAgICB5MCA9IDAsCiAgICAgICAgICAgICAgICAgIHIgPSA0KSwKICAgICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzRdLAogICAgICAgICAgICAgIGZpbGwgPSAiYmxhY2siLAogICAgICAgICAgICAgIHNpemUgPSAyKSArCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gbl9taW4sIAogICAgICAgICAgICAgICAgeG1heCA9IG5fbWF4LCAKICAgICAgICAgICAgICAgIHltaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB5bWF4ID0gbl9tYXgpLAogICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgIGNvbG9yID0gY29sX3BhbGV0dGVbMTBdKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycyA9IGNvbF9wYWxldHRlKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCk1ha2UgcHJldHR5IHdpdGggcGFsZXR0ZSBgUmV2b2x1Y2lvbmAuIFRoZSBjb2xvciBkZXBlbmRzIG9uIHRoZSBwb3NpdGlvbiBpbiB0aGUgZ3JpZDoKYGBge3J9CmNvbF9wYWxldHRlIDwtIG1leC5icmV3ZXIoIlJldm9sdWNpb24iKQoKcGF0aHNfZXgzIDwtIHBhdGhzX2V4MyAlPiUKICBtdXRhdGUocF9ncmlkID0gKHggKiB5KV4yLAogICAgICAgICBzaXplID0gMSAvIChhYnMoc3RlcCAtIGxfcGF0aC8yKSArIDEpKQoKZ2dwbG90KCkgKyAKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB4bWF4ID0gbl9tYXgsIAogICAgICAgICAgICAgICAgeW1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSBuX21heCksCiAgICAgICAgICAgIGZpbGwgPSAiYmxhY2siKSArCiAgZ2VvbV9jaXJjbGUoZGF0YSA9IHBhdGhzX2V4MywKICAgICAgICAgICAgICBhZXMoeDAgPSB4LAogICAgICAgICAgICAgICAgICB5MCA9IHksCiAgICAgICAgICAgICAgICAgIGZpbGwgPXBfZ3JpZCwKICAgICAgICAgICAgICAgICAgY29sb3IgPSBwX2dyaWQsCiAgICAgICAgICAgICAgICAgIHIgPSAxLjIgKiBzaXplICogcmVzKSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHBhdGhzX2V4MywKICAgICAgICAgICAgIGFlcyh4ID0geCAtIDEuMiAqIHNpemUgKiByZXMgKiBwaS80LAogICAgICAgICAgICAgICAgIHkgPSB5ICsgMS4yICogc2l6ZSAqIHJlcyAqIHBpLzQpLAogICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVs0XSwKICAgICAgICAgICAgIHNpemUgPSAwLjEpICsKICBnZW9tX2NpcmNsZShhZXMoeDAgPSAwLAogICAgICAgICAgICAgICAgICB5MCA9IDAsCiAgICAgICAgICAgICAgICAgIHIgPSA0KSwKICAgICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzRdLAogICAgICAgICAgICAgIGZpbGwgPSAiYmxhY2siLAogICAgICAgICAgICAgIHNpemUgPSAyKSArCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gbl9taW4sIAogICAgICAgICAgICAgICAgeG1heCA9IG5fbWF4LCAKICAgICAgICAgICAgICAgIHltaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB5bWF4ID0gbl9tYXgpLAogICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgIGNvbG9yID0gY29sX3BhbGV0dGVbMTBdKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycyA9IGNvbF9wYWxldHRlKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCk1ha2UgcHJldHR5IHdpdGggcGFsZXR0ZSBgUmV2b2x1Y2lvbmAgYnV0IG5vdyBjaGFuZ2UgdGhlIHJhdGUgb2YgY2hhbmdlIG9mIHRoZSBjb2xvcnM6CmBgYHtyfQpjb2xfcGFsZXR0ZSA8LSBtZXguYnJld2VyKCJSZXZvbHVjaW9uIikKCnBhdGhzX2V4MyA8LSBwYXRoc19leDMgJT4lCiAgbXV0YXRlKHBfZ3JpZCA9ICh4ICogeSleMiwKICAgICAgICAgc2l6ZSA9IDEgLyAoYWJzKHN0ZXAgLSBsX3BhdGgvMikgKyAxKSkKCmdncGxvdCgpICsgCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gbl9taW4sIAogICAgICAgICAgICAgICAgeG1heCA9IG5fbWF4LCAKICAgICAgICAgICAgICAgIHltaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB5bWF4ID0gbl9tYXgpLAogICAgICAgICAgICBmaWxsID0gImJsYWNrIikgKwogIGdlb21fY2lyY2xlKGRhdGEgPSBwYXRoc19leDMsCiAgICAgICAgICAgICAgYWVzKHgwID0geCwKICAgICAgICAgICAgICAgICAgeTAgPSB5LAogICAgICAgICAgICAgICAgICBmaWxsID0gcF9ncmlkXigxLzMpLAogICAgICAgICAgICAgICAgICBjb2xvciA9IHBfZ3JpZF4oMS8zKSwKICAgICAgICAgICAgICAgICAgciA9IDEuMiAqIHNpemUgKiByZXMpKSArCiAgZ2VvbV9wb2ludChkYXRhID0gcGF0aHNfZXgzLAogICAgICAgICAgICAgYWVzKHggPSB4IC0gMS4yICogc2l6ZSAqIHJlcyAqIHBpLzQsCiAgICAgICAgICAgICAgICAgeSA9IHkgKyAxLjIgKiBzaXplICogcmVzICogcGkvNCksCiAgICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzRdLAogICAgICAgICAgICAgc2l6ZSA9IDAuMSkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IG5fbWluLCB4ZW5kID0gbl9tYXgsIHkgPSAwLCB5ZW5kID0gMCksCiAgICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzRdLAogICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLCB4ZW5kID0gMCwgeSA9IG5fbWluLCB5ZW5kID0gbl9tYXgpLAogICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVs0XSwKICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV9jaXJjbGUoYWVzKHgwID0gMCwKICAgICAgICAgICAgICAgICAgeTAgPSAwLAogICAgICAgICAgICAgICAgICByID0gNCksCiAgICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVs0XSwKICAgICAgICAgICAgICBmaWxsID0gImJsYWNrIiwKICAgICAgICAgICAgICBzaXplID0gMykgKwogIGdlb21fcmVjdChhZXMoeG1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHhtYXggPSBuX21heCwgCiAgICAgICAgICAgICAgICB5bWluID0gbl9taW4sIAogICAgICAgICAgICAgICAgeW1heCA9IG5fbWF4KSwKICAgICAgICAgICAgZmlsbCA9IE5BLAogICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzRdLCAKICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzID0gY29sX3BhbGV0dGUpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpgYGAKCk1ha2UgcHJldHR5IHdpdGggcGFsZXR0ZSBgUmV2b2x1Y2lvbmAgYnV0IG5vdyB0aGUgY29sb3JzIGRlcGVuZCBvbiB0aGUgcG9zaXRpb24gb24gdGhlIHBhdGg6CmBgYHtyfQpjb2xfcGFsZXR0ZSA8LSBtZXguYnJld2VyKCJSZXZvbHVjaW9uIikKCnBhdGhzX2V4MyA8LSBwYXRoc19leDMgJT4lCiAgbXV0YXRlKHBfZ3JpZCA9ICh4ICogeSleMiwKICAgICAgICAgc2l6ZSA9IDEgLyAoYWJzKHN0ZXAgLSBsX3BhdGgvMikgKyAxKSkKCmdncGxvdCgpICsgCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gbl9taW4sIAogICAgICAgICAgICAgICAgeG1heCA9IG5fbWF4LCAKICAgICAgICAgICAgICAgIHltaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB5bWF4ID0gbl9tYXgpLAogICAgICAgICAgICBmaWxsID0gImJsYWNrIikgKwogIGdlb21fY2lyY2xlKGRhdGEgPSBwYXRoc19leDMsCiAgICAgICAgICAgICAgYWVzKHgwID0geCwKICAgICAgICAgICAgICAgICAgeTAgPSB5LAogICAgICAgICAgICAgICAgICBmaWxsID0gc3RlcCAtIGxfcGF0aC8yLAogICAgICAgICAgICAgICAgICBjb2xvciA9IHN0ZXAgLSBsX3BhdGgvMiwKICAgICAgICAgICAgICAgICAgciA9IDEuMiAqIHNpemUgKiByZXMpKSArCiAgZ2VvbV9wb2ludChkYXRhID0gcGF0aHNfZXgzLAogICAgICAgICAgICAgYWVzKHggPSB4IC0gMS4yICogc2l6ZSAqIHJlcyAqIHBpLzQsCiAgICAgICAgICAgICAgICAgeSA9IHkgKyAxLjIgKiBzaXplICogcmVzICogcGkvNCksCiAgICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzRdLAogICAgICAgICAgICAgc2l6ZSA9IDAuMSkgKwogIGdlb21fY2lyY2xlKGFlcyh4MCA9IDAsCiAgICAgICAgICAgICAgICAgIHkwID0gMCwKICAgICAgICAgICAgICAgICAgciA9IDQpLAogICAgICAgICAgICAgIGNvbG9yID0gY29sX3BhbGV0dGVbNF0sCiAgICAgICAgICAgICAgZmlsbCA9ICJibGFjayIsCiAgICAgICAgICAgICAgc2l6ZSA9IDIpICsKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB4bWF4ID0gbl9tYXgsIAogICAgICAgICAgICAgICAgeW1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSBuX21heCksCiAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVsxMF0pICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzID0gY29sX3BhbGV0dGUpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKQ2hhbmdlIHRoZSByZXNvbHV0aW9uOgpgYGB7cn0KIyBTZXQgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5CiNzZXQuc2VlZCgzNDYzNjMpCgojIFBhcmFtZXRlcnMgZm9yIGNyZWF0aW5nIHRoZSBwYXRocwpyZXMgPC0gMyAjIFJlc29sdXRpb24gZm9yIHRoZSBwYXRoLCBzbWFsbGVyIG51bWJlcnMgY3JlYXRlIG1vcmUgcG9pbnRzIHBlciBwYXRoL3Ntb290aGVyIHBhdGhzCm5faXRlciA8LSAyMCAjIE51bWJlciBvZiBpdGVyYXRpb25zIHBlciBwYXRoCm5fcGF0aCA8LSA1MDAwICMgTnVtYmVyIG9mIHBhdGhzCgojIFNhbXBsZSBzdGFydGluZyBwb2ludHMKc3RfcG9pbnQgPC0gZGF0YS5mcmFtZSh4ID0gcnVuaWYobl9wYXRoLCBuX21pbiwgbl9tYXgpLAogICAgICAgICAgICAgICAgICAgICAgICN4ID0gMiwKICAgICAgICAgICAgICAgICAgICAgICB5ID0gcnVuaWYobl9wYXRoLCBuX21pbiwgbl9tYXgpKQoKIyBJbml0aWFsaXplIGRhdGEgZnJhbWUgd2l0aCBwYXRocwpwYXRocyA8LSBkYXRhLmZyYW1lKHggPSBudW1lcmljKCksIHkgPSBudW1lcmljKCksIHN0ZXAgPSBudW1lcmljKCksIHBhdGggPSBudW1lcmljKCkpCgpmb3IocCBpbiAxOm5fcGF0aCl7CiAgcGF0aHMgPC0gcmJpbmQocGF0aHMsCiAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZShzdF9wb2ludFtwLF0sIHN0ZXAgPSAxLCBwYXRoID0gcCkpCiAgbmV4dF94IDwtIHN0X3BvaW50W3AsICJ4Il0KICBuZXh0X3kgPC0gc3RfcG9pbnRbcCwgInkiXQogIGZvcihpIGluIDE6bl9pdGVyKXsKICAgICMgV2l0aCB0aGUgbmV4dCBwb2ludCwgcmV0cmlldmUgdGhlIGFuZ2xlIG9mIHRoZSBjbG9zZXN0IHBvaW50IGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIGZsb3cKICAgIGFuZ2xlIDwtIGRmICU+JSAKICAgICAgbXV0YXRlKGQgPSBzcXJ0KCh4IC0gbmV4dF94KV4yICsgKHkgLSBuZXh0X3kpXjIpKSAlPiUKICAgICAgZmlsdGVyKGQgPT0gbWluKGQpKSAlPiUKICAgICAgcHVsbChhbmdsZSkKICAgICMgQ2FsY3VsYXRlIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbmV3IG5leHQgcG9pbnQgYW5kIGJpbmQgdG8gcGF0aHMKICAgIHBhdGhzIDwtIHJiaW5kKHBhdGhzLAogICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSh4ID0gbmV4dF94ICsgc2lnbihuZXh0X3gpICogcmVzICogY29zKGFuZ2xlKSwgIyBJbXBvcnRhbnQgdG8gbXVsdGlwbHkgYnkgdGhlIHNpZ24gb2YgdGhlIG5leHQgcG9pbnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IG5leHRfeSArIHNpZ24obmV4dF95KSAqIHJlcyAqIHNpbihhbmdsZSksICMgSW1wb3J0YW50IHRvIG11bHRpcGx5IGJ5IHRoZSBzaWduIG9mIHRoZSBuZXh0IHBvaW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXAgPSBpICsgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IHApKQogICAgIyBGaW5kIHRoZSBuZXh0IHN0YXJ0aW5nIHBvaW50IGZvciB0aGUgc2VhcmNoCiAgICBuZXh0X3ggPC0gc2xpY2VfdGFpbChwYXRocykgJT4lCiAgICAgIHB1bGwoeCkKICAgIG5leHRfeSA8LSBzbGljZV90YWlsKHBhdGhzKSAlPiUKICAgICAgcHVsbCh5KQogICAgCiAgICAjIENoZWNrIHRoZSBib3VuZGFyeSBjb25kaXRpb24KICAgIGJvdW5kYXJ5X2NvbmRpdGlvbiA8LSBuZXh0X3ggPCBuX21pbiB8IG5leHRfeCA+PSBuX21heCB8CiAgICAgIG5leHRfeSA8IG5fbWluIHwgbmV4dF95ID49IG5fbWF4CiAgICAjIElmIGF0IHRoZSBib3VuZGFyeSBzZXQgaSB0byBuX2l0ZXIgdG8gY29tcGxldGUgdGhlIGxvb3AKICAgIGlmIChib3VuZGFyeV9jb25kaXRpb24pIGJyZWFrCiAgfQp9CgojIFJlbmFtZSBwYXRocwoKcGF0aHNfZXg0IDwtIHBhdGhzCmBgYAoKUGxvdCBwYXRoczoKYGBge3IgcGF0aHMtZXg0fQojIEFkZCBsZW5ndGggb2YgcGF0aCB0byB0YWJsZToKcGF0aHNfZXg0IDwtIHBhdGhzX2V4NCAlPiUgCiAgbGVmdF9qb2luKHBhdGhzX2V4NCAlPiUKICAgICAgICAgICAgICBncm91cF9ieShwYXRoKSAlPiUKICAgICAgICAgICAgICBzdW1tYXJpemUobF9wYXRoID0gbigpLCAjIGxlbmd0aCBvZiBwYXRoCiAgICAgICAgICAgICAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpLAogICAgICAgICAgICBieSA9ICJwYXRoIikgCgpnZ3Bsb3QoKSArIAogIGdlb21fbGluZShkYXRhID0gcGF0aHNfZXg0LAogICAgICAgICAgICBhZXMoeCA9IHgsCiAgICAgICAgICAgICAgICB5ID0geSwKICAgICAgICAgICAgICAgIGdyb3VwID0gcGF0aCwKICAgICAgICAgICAgICAgIGNvbG9yID0gc3RlcCAtIGxfcGF0aC8yKSwKICAgICAgICAgICAgc2l6ZSA9IDAuMSkgKwogIGdlb21fc2VnbWVudChkYXRhID0gZGYsCiAgICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgeGVuZCA9IHhlbmQsCiAgICAgICAgICAgICAgICAgICB5ZW5kID0geWVuZCkpICsKICBnZW9tX3BvaW50KGRhdGEgPSBkZiwKICAgICAgICAgICAgIGFlcyh4ID0geGVuZCwgCiAgICAgICAgICAgICAgICAgeSA9eWVuZCkpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3J9CmNvbF9wYWxldHRlIDwtIG1leC5icmV3ZXIoIlJldm9sdWNpb24iKQoKcGF0aHNfZXg0IDwtIHBhdGhzX2V4NCAlPiUKICBtdXRhdGUocF9ncmlkID0gKHggKiB5KV4yLAogICAgICAgICBzaXplID0gMSAvIChhYnMoc3RlcCAtIGxfcGF0aC8yKSArIDEpKQoKZ2dwbG90KCkgKyAKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB4bWF4ID0gbl9tYXgsIAogICAgICAgICAgICAgICAgeW1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSBuX21heCksCiAgICAgICAgICAgIGZpbGwgPSAiYmxhY2siKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBwYXRoc19leDQgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKHggPiBuX21pbiAmIHggPCBuX21heCwgCiAgICAgICAgICAgICAgICAgICAgIHkgPiBuX21pbiAmIHkgPCBuX21heCksCiAgICAgICAgICAgICAgYWVzKHggPSB4LAogICAgICAgICAgICAgICAgICB5ID0geSwKICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBwYXRoLAogICAgICAgICAgICAgICAgICBjb2xvciA9IHBfZ3JpZF4oMS8zKSkpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSBuX21pbiwgeGVuZCA9IG5fbWF4LCB5ID0gMCwgeWVuZCA9IDApLAogICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVsxMF0sCiAgICAgICAgICAgICBzaXplID0gMykgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IDAsIHhlbmQgPSAwLCB5ID0gbl9taW4sIHllbmQgPSBuX21heCksCiAgICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzEwXSwKICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV9jaXJjbGUoYWVzKHgwID0gMCwKICAgICAgICAgICAgICAgICAgeTAgPSAwLAogICAgICAgICAgICAgICAgICByID0gNCksCiAgICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVsxMF0sCiAgICAgICAgICAgICAgZmlsbCA9ICJibGFjayIsCiAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB4bWF4ID0gbl9tYXgsIAogICAgICAgICAgICAgICAgeW1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSBuX21heCksCiAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVsxMF0sIAogICAgICAgICAgICBzaXplID0gMykgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvcnMgPSBjb2xfcGFsZXR0ZSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lX3ZvaWQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgoKCiMjIEV4cGVyaW1lbnRzIHdpdGggYW5nbGUgYW5kIHJlc29sdXRpb25zCgoKYGBge3J9CiMgU2l6ZSBvZiBncmlkCm5fbWluIDwtIC0xNyAKbl9tYXggPC0gMTgKIyBMZW5ndGggb2Ygc2VnbWVudApsIDwtIHNxcnQoMikgKyAwLjEKCmRmIDwtIGRhdGEuZnJhbWUoZXhwYW5kLmdyaWQoeCA9IHNlcShuX21pbiwgbl9tYXgsIDEpLCB5ID0gc2VxKG5fbWluLCBuX21heCwgMSkpKQpgYGAKCgpDcmVhdGUgbmV3IGZsb3cgZmllbGQ6CmBgYHtyfQojIE9mZnNldHMKeF9vIDwtIC0xNQp5X28gPC0gNQppbml0X3IgPC0gMApkX2FuZ2xlIDwtIDIKCiMgcmVtb3ZlIHRoZSB2YWxlbmNlCmRmIDwtIGRmICU+JQogIG11dGF0ZShhbmdsZSA9ICgoKHggLSB4X28pICogKHkgLSB5X28pKSAvKG5fbWF4IC0gbl9taW4pXjIgKiBkX2FuZ2xlICogcGkgKyBpbml0X3IgKiBwaSksIyAqIHNpZ24oeCAqIHkpLCAjIGFkZCB0aGUgc2lnbnMKICAgICAgICAgeGVuZCA9ICh4ICsgbCAqIGNvcyhhbmdsZSkpLAogICAgICAgICB5ZW5kID0gKHkgKyBsICogc2luKGFuZ2xlKSkpCgpkZiAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgeGVuZCA9IHhlbmQsCiAgICAgICAgICAgICAgICAgICB5ZW5kID0geWVuZCkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0geGVuZCwgCiAgICAgICAgICAgICAgICAgeSA9eWVuZCkpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkKYGBgCgpBZGQgb2JzdGFjbGVzOgpgYGB7cn0KZGYgPC0gZGYgJT4lCiAgbXV0YXRlKHIxID0gc3FydCgoeCAtIDgpXjIgKyAoeSAtIDgpXjIpLAogICAgICAgICByMiA9IHNxcnQoKHggKyA4KV4yICsgKHkgKyA4KV4yKSkgJT4lCiAgZmlsdGVyKHIxID4gNCwKICAgICAgICAgcjIgPiA0KQoKZGYgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IHgsCiAgICAgICAgICAgICAgICAgICB5ID0geSwKICAgICAgICAgICAgICAgICAgIHhlbmQgPSB4ZW5kLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IHllbmQpKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IHhlbmQsIAogICAgICAgICAgICAgICAgIHkgPXllbmQpKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpCgpgYGAKCkNoYW5nZSB0aGUgcmVzb2x1dGlvbjoKYGBge3J9CiMgU2V0IHNlZWQgZm9yIHJlcHJvZHVjaWJpbGl0eQojc2V0LnNlZWQoMzQ2MzYzKQoKIyBQYXJhbWV0ZXJzIGZvciBjcmVhdGluZyB0aGUgcGF0aHMKcmVzIDwtIDMgIyBSZXNvbHV0aW9uIGZvciB0aGUgcGF0aCwgc21hbGxlciBudW1iZXJzIGNyZWF0ZSBtb3JlIHBvaW50cyBwZXIgcGF0aC9zbW9vdGhlciBwYXRocwpuX2l0ZXIgPC0gNTAgIyBOdW1iZXIgb2YgaXRlcmF0aW9ucyBwZXIgcGF0aApuX3BhdGggPC0gNTAwMCAjIE51bWJlciBvZiBwYXRocwoKIyBTYW1wbGUgc3RhcnRpbmcgcG9pbnRzCnN0X3BvaW50IDwtIGRhdGEuZnJhbWUoeCA9IHJ1bmlmKG5fcGF0aCwgbl9taW4sIG5fbWF4KSwKICAgICAgICAgICAgICAgICAgICAgICAjeCA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgeSA9IHJ1bmlmKG5fcGF0aCwgbl9taW4sIG5fbWF4KSkgJT4lCiAgbXV0YXRlKHIxID0gc3FydCgoeCAtIDgpXjIgKyAoeSAtIDgpXjIpLAogICAgICAgICByMiA9IHNxcnQoKHggKyA4KV4yICsgKHkgKyA4KV4yKSkgJT4lCiAgZmlsdGVyKHIxID4gNCwKICAgICAgICAgcjIgPiA0KSAlPiUKICBzZWxlY3QoLXN0YXJ0c193aXRoKCJyIikpCgojIFVwZGF0ZSBudW1iZXIgb2YgcGF0aHMgdG8gYWNjb3VudCBmb3IgdGhlIHN0YXJ0aW5nIHBvaW5zIGVsaW1pbmF0ZWQgZHVlIHRvIG9ic3RhY2xlcwpuX3BhdGggPC0gbnJvdyhzdF9wb2ludCkKCiMgSW5pdGlhbGl6ZSBkYXRhIGZyYW1lIHdpdGggcGF0aHMKcGF0aHMgPC0gZGF0YS5mcmFtZSh4ID0gbnVtZXJpYygpLCB5ID0gbnVtZXJpYygpLCBzdGVwID0gbnVtZXJpYygpLCBwYXRoID0gbnVtZXJpYygpKQoKZm9yKHAgaW4gMTpuX3BhdGgpewogIHBhdGhzIDwtIHJiaW5kKHBhdGhzLAogICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoc3RfcG9pbnRbcCxdLCBzdGVwID0gMSwgcGF0aCA9IHApKQogIG5leHRfeCA8LSBzdF9wb2ludFtwLCAieCJdCiAgbmV4dF95IDwtIHN0X3BvaW50W3AsICJ5Il0KICBmb3IoaSBpbiAxOm5faXRlcil7CiAgICAjIFdpdGggdGhlIG5leHQgcG9pbnQsIHJldHJpZXZlIHRoZSBhbmdsZSBvZiB0aGUgY2xvc2VzdCBwb2ludCBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSBmbG93CiAgICBhbmdsZSA8LSBkZiAlPiUgCiAgICAgIG11dGF0ZShkID0gc3FydCgoeCAtIG5leHRfeCleMiArICh5IC0gbmV4dF95KV4yKSkgJT4lCiAgICAgIGZpbHRlcihkID09IG1pbihkKSkKICAgIG1pbl9kIDwtIGFuZ2xlICU+JSBwdWxsKGQpCiAgICBhbmdsZSA8LSBhbmdsZSAlPiUgcHVsbChhbmdsZSkKICAgICMgQ2FsY3VsYXRlIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbmV3IG5leHQgcG9pbnQgYW5kIGJpbmQgdG8gcGF0aHMKICAgIHBhdGhzIDwtIHJiaW5kKHBhdGhzLAogICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSh4ID0gbmV4dF94ICsgcmVzICogY29zKGFuZ2xlKSwgIyBSZW1vdmVkIHRoZSB2YWxlbmNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBuZXh0X3kgKyByZXMgKiBzaW4oYW5nbGUpLCAjIFJlbW92ZWQgdGhlIHZhbGVuY2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCA9IGkgKyAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gcCkpCiAgICAjIEZpbmQgdGhlIG5leHQgc3RhcnRpbmcgcG9pbnQgZm9yIHRoZSBzZWFyY2gKICAgIG5leHRfeCA8LSBzbGljZV90YWlsKHBhdGhzKSAlPiUKICAgICAgcHVsbCh4KQogICAgbmV4dF95IDwtIHNsaWNlX3RhaWwocGF0aHMpICU+JQogICAgICBwdWxsKHkpCiAgICAKICAgICMgQ2hlY2sgdGhlIGJvdW5kYXJ5IGNvbmRpdGlvbgogICAgYm91bmRhcnlfY29uZGl0aW9uIDwtIG5leHRfeCA8IG5fbWluIHwgbmV4dF94ID49IG5fbWF4IHwKICAgICAgbmV4dF95IDwgbl9taW4gfCBuZXh0X3kgPj0gbl9tYXggfCBtaW5fZCA+IHNxcnQoMikgKyAwLjEKICAgICMgSWYgYXQgdGhlIGJvdW5kYXJ5IHNldCBpIHRvIG5faXRlciB0byBjb21wbGV0ZSB0aGUgbG9vcAogICAgaWYgKGJvdW5kYXJ5X2NvbmRpdGlvbikgYnJlYWsKICB9Cn0KCiMgUmVuYW1lIHBhdGhzCgpwYXRoc19leDUgPC0gcGF0aHMKYGBgCgpQbG90IHBhdGhzOgpgYGB7ciBwYXRocy1leDV9CiMgQWRkIGxlbmd0aCBvZiBwYXRoIHRvIHRhYmxlOgpwYXRoc19leDUgPC0gcGF0aHNfZXg1ICU+JSAKICBsZWZ0X2pvaW4ocGF0aHNfZXg1ICU+JQogICAgICAgICAgICAgIGdyb3VwX2J5KHBhdGgpICU+JQogICAgICAgICAgICAgIHN1bW1hcml6ZShsX3BhdGggPSBuKCksICMgbGVuZ3RoIG9mIHBhdGgKICAgICAgICAgICAgICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIiksCiAgICAgICAgICAgIGJ5ID0gInBhdGgiKSAKCmdncGxvdCgpICsgCiAgZ2VvbV9wYXRoKGRhdGEgPSBwYXRoc19leDUsCiAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgZ3JvdXAgPSBwYXRoKSwKICAgICAgICAgICAgY29sb3IgPSAiYmx1ZSIsCiAgICAgICAgICAgIHNpemUgPSAxKSArCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBkZiwKICAgICAgICAgICAgICAgYWVzKHggPSB4LAogICAgICAgICAgICAgICAgICAgeSA9IHksCiAgICAgICAgICAgICAgICAgICB4ZW5kID0geGVuZCwKICAgICAgICAgICAgICAgICAgIHllbmQgPSB5ZW5kKSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGRmLAogICAgICAgICAgICAgYWVzKHggPSB4ZW5kLCAKICAgICAgICAgICAgICAgICB5ID15ZW5kKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lX3ZvaWQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpPYnN0YWNsZSBhdm9pZGFuY2Ugbm90IHdvcmtpbmcgZ3JlYXQsIHdvbmRlciB3aHkuCgpQcmV0dGlmeToKYGBge3J9CmNvbF9wYWxldHRlIDwtIG1leC5icmV3ZXIoIlJldm9sdWNpb24iKQoKcGF0aHNfZXg1IDwtIHBhdGhzX2V4NSAlPiUKICBtdXRhdGUocF9ncmlkID0gKCh4IC0gbl9taW4pICogKHkgLSBuX21pbiApKV4yLAogICAgICAgICBzaXplID0gMSAvIChhYnMoc3RlcCAtIGxfcGF0aC8yKSArIDEpKQoKcGxvdDEgPC0gZ2dwbG90KCkgKyAKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB4bWF4ID0gbl9tYXgsIAogICAgICAgICAgICAgICAgeW1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSBuX21heCksCiAgICAgICAgICAgIGZpbGwgPSAiYmxhY2siKSArCiAgZ2VvbV9wYXRoKGRhdGEgPSBwYXRoc19leDUgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKHggPiBuX21pbiAmIHggPCBuX21heCwKICAgICAgICAgICAgICAgICAgICAgeSA+IG5fbWluICYgeSA8IG5fbWF4KSwKICAgICAgICAgICAgICBhZXMoeCA9IHgsCiAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICBncm91cCA9IHBhdGgsCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gcF9ncmlkXigxLzMpKSkgKwogIGdlb21fY2lyY2xlKGFlcyh4MCA9IC04LAogICAgICAgICAgICAgICAgICB5MCA9IC04LAogICAgICAgICAgICAgICAgICByID0gNCksCiAgICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVs0XSwKICAgICAgICAgICAgICBmaWxsID0gY29sX3BhbGV0dGVbOF0sCiAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICAgZ2VvbV9jaXJjbGUoYWVzKHgwID0gOCwKICAgICAgICAgICAgICAgICAgIHkwID0gOCwKICAgICAgICAgICAgICAgICAgIHIgPSA0KSwKICAgICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVs0XSwKICAgICAgICAgICAgICAgZmlsbCA9IGNvbF9wYWxldHRlWzFdLAogICAgICAgICAgICAgICBzaXplID0gMykgKwogIGdlb21fcmVjdChhZXMoeG1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHhtYXggPSBuX21heCwgCiAgICAgICAgICAgICAgICB5bWluID0gbl9taW4sIAogICAgICAgICAgICAgICAgeW1heCA9IG5fbWF4KSwKICAgICAgICAgICAgZmlsbCA9IE5BLAogICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzhdLCAKICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzID0gY29sX3BhbGV0dGUpICsKICBjb29yZF9lcXVhbCgpICsKICB0aGVtZV92b2lkKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpwbG90MQpgYGAKCmBgYHtyfQpjb2xfcGFsZXR0ZSA8LSBtZXguYnJld2VyKCJBdGVudGFkbyIpCgpwYXRoc19leDUgPC0gcGF0aHNfZXg1ICU+JQogIG11dGF0ZShwX2dyaWQgPSAoKHggLSBuX21pbikgKiAoeSAtIG5fbWluICkpXjIsCiAgICAgICAgIHNpemUgPSAxIC8gKGFicyhzdGVwIC0gbF9wYXRoLzIpICsgMSkpCgpwbG90MiA8LSBnZ3Bsb3QoKSArIAogIGdlb21fcmVjdChhZXMoeG1pbiA9IC1uX21pbiwgCiAgICAgICAgICAgICAgICB4bWF4ID0gLW5fbWF4LCAKICAgICAgICAgICAgICAgIHltaW4gPSBuX21pbiwgCiAgICAgICAgICAgICAgICB5bWF4ID0gbl9tYXgpLAogICAgICAgICAgICBmaWxsID0gImJsYWNrIikgKwogIGdlb21fcGF0aChkYXRhID0gcGF0aHNfZXg1ICU+JQogICAgICAgICAgICAgIGZpbHRlcih4ID4gbl9taW4gJiB4IDwgbl9tYXgsCiAgICAgICAgICAgICAgICAgICAgIHkgPiBuX21pbiAmIHkgPCBuX21heCksCiAgICAgICAgICAgICAgYWVzKHggPSAteCwKICAgICAgICAgICAgICAgICAgeSA9IHksCiAgICAgICAgICAgICAgICAgIGdyb3VwID0gcGF0aCwKICAgICAgICAgICAgICAgICAgY29sb3IgPSBwX2dyaWReKDEvMykpKSArCiAgZ2VvbV9jaXJjbGUoYWVzKHgwID0gOCwKICAgICAgICAgICAgICAgICAgeTAgPSAtOCwKICAgICAgICAgICAgICAgICAgciA9IDQpLAogICAgICAgICAgICAgIGNvbG9yID0gY29sX3BhbGV0dGVbNF0sCiAgICAgICAgICAgICAgZmlsbCA9IGNvbF9wYWxldHRlWzhdLAogICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgIGdlb21fY2lyY2xlKGFlcyh4MCA9IC04LAogICAgICAgICAgICAgICAgICAgeTAgPSA4LAogICAgICAgICAgICAgICAgICAgciA9IDQpLAogICAgICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzRdLAogICAgICAgICAgICAgICBmaWxsID0gY29sX3BhbGV0dGVbMV0sCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gLW5fbWluLCAKICAgICAgICAgICAgICAgIHhtYXggPSAtbl9tYXgsIAogICAgICAgICAgICAgICAgeW1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSBuX21heCksCiAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVs4XSwgCiAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycyA9IGNvbF9wYWxldHRlKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKcGxvdDIKYGBgCgpgYGB7cn0KY29sX3BhbGV0dGUgPC0gbWV4LmJyZXdlcigiQWxhY2VuYSIpCgpwYXRoc19leDUgPC0gcGF0aHNfZXg1ICU+JQogIG11dGF0ZShwX2dyaWQgPSAoKHggLSBuX21pbikgKiAoeSAtIG5fbWluICkpXjIsCiAgICAgICAgIHNpemUgPSAxIC8gKGFicyhzdGVwIC0gbF9wYXRoLzIpICsgMSkpCgpwbG90MyA8LSBnZ3Bsb3QoKSArIAogIGdlb21fcmVjdChhZXMoeG1pbiA9IG5fbWluLCAKICAgICAgICAgICAgICAgIHhtYXggPSBuX21heCwgCiAgICAgICAgICAgICAgICB5bWluID0gLW5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSAtbl9tYXgpLAogICAgICAgICAgICBmaWxsID0gImJsYWNrIikgKwogIGdlb21fcGF0aChkYXRhID0gcGF0aHNfZXg1ICU+JQogICAgICAgICAgICAgIGZpbHRlcih4ID4gbl9taW4gJiB4IDwgbl9tYXgsCiAgICAgICAgICAgICAgICAgICAgIHkgPiBuX21pbiAmIHkgPCBuX21heCksCiAgICAgICAgICAgICAgYWVzKHggPSB4LAogICAgICAgICAgICAgICAgICB5ID0gLXksCiAgICAgICAgICAgICAgICAgIGdyb3VwID0gcGF0aCwKICAgICAgICAgICAgICAgICAgY29sb3IgPSBwX2dyaWReKDEvMykpKSArCiAgZ2VvbV9jaXJjbGUoYWVzKHgwID0gOCwKICAgICAgICAgICAgICAgICAgeTAgPSAtOCwKICAgICAgICAgICAgICAgICAgciA9IDQpLAogICAgICAgICAgICAgIGNvbG9yID0gY29sX3BhbGV0dGVbNF0sCiAgICAgICAgICAgICAgZmlsbCA9IGNvbF9wYWxldHRlWzhdLAogICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgIGdlb21fY2lyY2xlKGFlcyh4MCA9IC04LAogICAgICAgICAgICAgICAgICAgeTAgPSA4LAogICAgICAgICAgICAgICAgICAgciA9IDQpLAogICAgICAgICAgICAgICBjb2xvciA9IGNvbF9wYWxldHRlWzRdLAogICAgICAgICAgICAgICBmaWxsID0gY29sX3BhbGV0dGVbMV0sCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gbl9taW4sIAogICAgICAgICAgICAgICAgeG1heCA9IG5fbWF4LCAKICAgICAgICAgICAgICAgIHltaW4gPSAtbl9taW4sIAogICAgICAgICAgICAgICAgeW1heCA9IC1uX21heCksCiAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgY29sb3IgPSBjb2xfcGFsZXR0ZVs4XSwgCiAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycyA9IGNvbF9wYWxldHRlKSArCiAgY29vcmRfZXF1YWwoKSArCiAgdGhlbWVfdm9pZCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKcGxvdDMKYGBgCgoKYGBge3J9CmNvbF9wYWxldHRlIDwtIG1leC5icmV3ZXIoIlJvbmRhIikKCnBhdGhzX2V4NSA8LSBwYXRoc19leDUgJT4lCiAgbXV0YXRlKHBfZ3JpZCA9ICgoeCAtIG5fbWluKSAqICh5IC0gbl9taW4gKSleMiwKICAgICAgICAgc2l6ZSA9IDEgLyAoYWJzKHN0ZXAgLSBsX3BhdGgvMikgKyAxKSkKCnBsb3Q0IDwtIGdncGxvdCgpICsgCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gLW5fbWluLCAKICAgICAgICAgICAgICAgIHhtYXggPSAtbl9tYXgsIAogICAgICAgICAgICAgICAgeW1pbiA9IC1uX21pbiwgCiAgICAgICAgICAgICAgICB5bWF4ID0gLW5fbWF4KSwKICAgICAgICAgICAgZmlsbCA9ICJibGFjayIpICsKICBnZW9tX3BhdGgoZGF0YSA9IHBhdGhzX2V4NSAlPiUKICAgICAgICAgICAgICBmaWx0ZXIoeCA+IG5fbWluICYgeCA8IG5fbWF4LAogICAgICAgICAgICAgICAgICAgICB5ID4gbl9taW4gJiB5IDwgbl9tYXgpLAogICAgICAgICAgICAgIGFlcyh4ID0gLXgsCiAgICAgICAgICAgICAgICAgIHkgPSAteSwKICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBwYXRoLAogICAgICAgICAgICAgICAgICBjb2xvciA9IHBfZ3JpZF4oMS8zKSkpICsKICBnZW9tX2NpcmNsZShhZXMoeDAgPSAtOCwKICAgICAgICAgICAgICAgICAgeTAgPSAtOCwKICAgICAgICAgICAgICAgICAgciA9IDQpLAogICAgICAgICAgICAgIGNvbG9yID0gY29sX3BhbGV0dGVbNF0sCiAgICAgICAgICAgICAgZmlsbCA9IGNvbF9wYWxldHRlWzhdLAogICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgIGdlb21fY2lyY2xlKGFlcyh4MCA9IDgsCiAgICAgICAgICAgICAgICAgICB5MCA9IDgsCiAgICAgICAgICAgICAgICAgICByID0gNCksCiAgICAgICAgICAgICAgIGNvbG9yID0gY29sX3BhbGV0dGVbNF0sCiAgICAgICAgICAgICAgIGZpbGwgPSBjb2xfcGFsZXR0ZVsxXSwKICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSAtbl9taW4sIAogICAgICAgICAgICAgICAgeG1heCA9IC1uX21heCwgCiAgICAgICAgICAgICAgICB5bWluID0gLW5fbWluLCAKICAgICAgICAgICAgICAgIHltYXggPSAtbl9tYXgpLAogICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgIGNvbG9yID0gY29sX3BhbGV0dGVbOF0sIAogICAgICAgICAgICBzaXplID0gMykgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvcnMgPSBjb2xfcGFsZXR0ZSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIHRoZW1lX3ZvaWQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCnBsb3Q0CmBgYAoKYGBge3IgZmlnLmhlaWdodD0xMH0KbGlicmFyeShwYXRjaHdvcmspCgoocGxvdDEgKyBwbG90MikgLyAocGxvdDMgKyBwbG90NCkKYGBgCgo=